package com.maodou.core.datastore.storage

import android.content.Context
import com.squareup.moshi.Moshi
import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
import com.tencent.mmkv.MMKV

/**
 * MMKV 实现的 KV 存储，支持基本类型与通过 Moshi 序列化的对象。
 */
class MmkvKeyValueStorage private constructor(
    private val mmkv: MMKV,
    private val moshi: Moshi,
) : KeyValueStorage {

    override fun setLoggedIn(value: Boolean) {
        mmkv.encode(KEY_LOGGED_IN, value)
    }

    override fun isLoggedIn(): Boolean = mmkv.decodeBool(KEY_LOGGED_IN, false)

    override fun clearAll() {
        mmkv.clearAll()
    }

    // 通用存储方法实现
    override fun putString(key: String, value: String?) {
        if (value == null) {
            mmkv.removeValueForKey(key)
        } else {
            mmkv.encode(key, value)
        }
    }

    override fun getString(key: String, defaultValue: String?): String? {
        return mmkv.decodeString(key, defaultValue)
    }

    override fun putBoolean(key: String, value: Boolean) {
        mmkv.encode(key, value)
    }

    override fun getBoolean(key: String, defaultValue: Boolean): Boolean {
        return mmkv.decodeBool(key, defaultValue)
    }

    override fun putInt(key: String, value: Int) {
        mmkv.encode(key, value)
    }

    override fun getInt(key: String, defaultValue: Int): Int {
        return mmkv.decodeInt(key, defaultValue)
    }

    override fun putLong(key: String, value: Long) {
        mmkv.encode(key, value)
    }

    override fun getLong(key: String, defaultValue: Long): Long {
        return mmkv.decodeLong(key, defaultValue)
    }

    override fun putFloat(key: String, value: Float) {
        mmkv.encode(key, value)
    }

    override fun getFloat(key: String, defaultValue: Float): Float {
        return mmkv.decodeFloat(key, defaultValue)
    }

    override fun putDouble(key: String, value: Double) {
        mmkv.encode(key, value)
    }

    override fun getDouble(key: String, defaultValue: Double): Double {
        return mmkv.decodeDouble(key, defaultValue)
    }

    override fun <T> putObject(key: String, value: T?, clazz: Class<T>) {
        if (value == null) {
            mmkv.removeValueForKey(key)
            return
        }
        val adapter = moshi.adapter(clazz)
        val json = adapter.toJson(value)
        mmkv.encode(key, json)
    }

    override fun <T> getObject(key: String, clazz: Class<T>): T? {
        val json = mmkv.decodeString(key) ?: return null
        val adapter = moshi.adapter(clazz)
        return runCatching { adapter.fromJson(json) }.getOrNull()
    }

    override fun remove(key: String) {
        mmkv.removeValueForKey(key)
    }

    override fun contains(key: String): Boolean {
        return mmkv.containsKey(key)
    }

    companion object {
        private const val KEY_LOGGED_IN = "kv_logged_in"
        private const val KEY_LOGIN_INFO = "kv_login_info"

        /**
         * 创建默认实例。
         * @param context Application Context
         * @param moshi 可选：传入全局 Moshi（若为空则内部创建带 Kotlin 反射的 Moshi）
         * @param mmkvId 可选：指定自定义 MMKV 实例 ID，默认使用 "maodou_kv"
         */
        @JvmStatic
        fun create(
            context: Context,
            moshi: Moshi? = null,
            mmkvId: String = "maodou_kv",
        ): MmkvKeyValueStorage {
            MMKV.initialize(context.applicationContext)
            val mmkv = MMKV.mmkvWithID(mmkvId, MMKV.MULTI_PROCESS_MODE)
            val effectiveMoshi = moshi ?: Moshi.Builder()
                .add(KotlinJsonAdapterFactory())
                .build()
            return MmkvKeyValueStorage(mmkv, effectiveMoshi)
        }
    }
}